package com.ld.shieldsb.common.composition.util;

import java.security.NoSuchAlgorithmException;

import org.mindrot.jbcrypt.BCrypt;

import com.ld.shieldsb.common.core.encryptor.AesEncryptor;
import com.ld.shieldsb.common.core.encryptor.BlowfishEncryptor;
import com.ld.shieldsb.common.core.encryptor.DesEncryptor;
import com.ld.shieldsb.common.core.encryptor.EncodeUtils;
import com.ld.shieldsb.common.core.encryptor.EorEncryptor;
import com.ld.shieldsb.common.core.encryptor.Md5Encryptor;
import com.ld.shieldsb.common.core.encryptor.Sha1Encryptor;
import com.ld.shieldsb.common.core.util.StringUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 加密解密工具类，AES，DES，建议在项目中new对象
 * 
 * @ClassName SecurityService
 * @author <a href="mailto:donggongai@126.com" target="_blank">kevin</a>
 * @date 2016年8月25日 下午2:54:43
 *
 */
@Slf4j
public class SecurityUtil {
    public static String SIMPLE_SECRET_KEY_RW = null; // "wefoundlove"; // 简单加密的密钥（读写），在具体项目中赋值
    public static String SIMPLE_SECRET_KEY_R = null; // "wefoundlove_r"; // 简单加密的密钥（只读），在具体项目中赋值
    public static String DES_SECRET_KEY = null; // "we_found_love"; // DES加密的密钥，在具体项目中赋值
    public static Integer EOR_SECRET_KEY_R = null; // // 异或运算的密钥（只读），在具体项目中赋值

    /**
     * 
     * SHA1加密（不可逆）
     * 
     * @Title SHA1
     * @param data
     *            要加密字符
     * @return
     * @throws NoSuchAlgorithmException
     *             String
     */
    public final static String sha1(String data) {
        byte[] b = Sha1Encryptor.sha1(data.getBytes());
        return EncodeUtils.encodeHex(b);
    }

    /**
     * 
     * MD5加密（不可逆）
     * 
     * @Title MD5
     * @param data
     *            要加密字符
     * @return
     * @throws NoSuchAlgorithmException
     *             String
     */
    public final static String md5(String data) {
        byte[] b = Md5Encryptor.md5(data.getBytes());
        return EncodeUtils.encodeHex(b);
    }

    /**
     * 
     * 用户提交信息加密方式
     * 
     * @Title encryptIn
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static String desEncrypt(String strIn) {
        if (DES_SECRET_KEY == null) {
            log.error("DES_SECRET_KEY未赋值，请在项目中赋值！");
        }
        return DesEncryptor.encode(strIn, DES_SECRET_KEY);
    }

    /**
     * 
     * 用户提交信息解密方式
     * 
     * @Title encryptIn
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static String desDecrypt(String strIn) {
        if (DES_SECRET_KEY == null) {
            log.error("DES_SECRET_KEY未赋值，请在项目中赋值！");
        }
        return DesEncryptor.decode(strIn, DES_SECRET_KEY);
    }

    /**
     * bcrypt加密（使用了bcrypt hash算法）
     * 
     * @Title bcryptEncrypt
     * @author 吕凯
     * @date 2018年12月5日 上午11:27:46
     * @param strIn
     * @return
     * @throws Exception
     *             String
     */
    public static String bcryptEncrypt(String plaintext) throws Exception {
        String salt = "$2a$10$" + StringUtils.getRandomStr(23); // 不少于30位，前7位固定
//        System.out.println("salt:" + salt);
        String hashedPassword = BCrypt.hashpw(plaintext, salt);
        return hashedPassword;
    }

    /**
     * bcrypt算法加密过的文本是否匹配
     * 
     * @Title bcryptMatch
     * @author 吕凯
     * @date 2018年12月5日 上午11:34:12
     * @param plaintext
     * @param hashed
     * @return
     * @throws Exception
     *             boolean
     */
    public static boolean bcryptMatch(String plaintext, String hashed) throws Exception {
        return BCrypt.checkpw(plaintext, hashed);
    }

    /**
     * 
     * 简单加密，会保存的用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title encryptIn
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static String simpleEncrypt(String strIn) {
        return simpleWriteEncrypt(strIn);
    }

    public static String simpleWriteEncrypt(String strIn) {
        if (SIMPLE_SECRET_KEY_RW == null) {
            log.error("SIMPLE_SECRET_KEY_RW未赋值，请在项目中赋值！");
        }
        return DesEncryptor.encode(strIn, SIMPLE_SECRET_KEY_RW);
    }

    /**
     * 
     * 简单解密，会保存的用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title encryptIn
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static String simpleDecrypt(String strIn) {
        return simpleWriteDecrypt(strIn);
    }

    public static String simpleWriteDecrypt(String strIn) {
        if (SIMPLE_SECRET_KEY_RW == null) {
            log.error("SIMPLE_SECRET_KEY_RW未赋值，请在项目中赋值！");
        }
        return DesEncryptor.decode(strIn, SIMPLE_SECRET_KEY_RW);
    }

    /**
     * 
     * 简单加密，只读取的用此方法，注意可能保存的一定不能使用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title simpleReadEncrypt
     * @author 吕凯
     * @date 2019年8月2日 下午4:59:01
     * @param strIn
     * @return String
     */
    public static String simpleReadEncrypt(String strIn) {
        if (SIMPLE_SECRET_KEY_R == null) {
            log.error("SIMPLE_SECRET_KEY_R未赋值，请在项目中赋值！");
        }
        return DesEncryptor.encode(strIn, SIMPLE_SECRET_KEY_R);
    }

    /**
     * 
     * 简单解密，只读取的用此方法，注意可能保存的一定不能使用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title simpleReadDecrypt
     * @author 吕凯
     * @date 2019年8月2日 下午4:59:20
     * @param strIn
     * @return String
     */
    public static String simpleReadDecrypt(String strIn) {
        if (SIMPLE_SECRET_KEY_R == null) {
            log.error("SIMPLE_SECRET_KEY_R未赋值，请在项目中赋值！");
        }
        return DesEncryptor.decode(strIn, SIMPLE_SECRET_KEY_R);
    }

    /**
     * 
     * 查询加密（异或），只读取的用此方法，注意可能保存的一定不能使用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title queryEncrypt
     * @author 吕凯
     * @date 2019年8月5日 上午9:24:56
     * @param strIn
     * @return String
     */
    public static String queryEncrypt(String strIn) {
        if (SIMPLE_SECRET_KEY_R == null) {
            log.error("SIMPLE_SECRET_KEY_R未赋值，请在项目中赋值！");
        }
        return EorEncryptor.encode(strIn, EOR_SECRET_KEY_R);
    }

    /**
     * 查询解密（异或），只读取的用此方法，注意可能保存的一定不能使用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title queryDecrypt
     * @author 吕凯
     * @date 2019年8月5日 上午9:24:43
     * @param strIn
     * @return String
     */
    public static String queryDecrypt(String strIn) throws Exception {
        if (EOR_SECRET_KEY_R == null) {
            log.error("EOR_SECRET_KEY_R未赋值，请在项目中赋值！");
        }
        return EorEncryptor.decode(strIn, EOR_SECRET_KEY_R);
    }

    public static void main(String[] args) throws Exception {
        String sha1String = sha1("test");
        System.out.println(sha1String);
        String md5String = md5("test");
        System.out.println(md5String);
        String encode = desEncrypt("test");
        System.out.println(encode);
        System.out.println(desDecrypt(encode));

        AesEncryptor ss = new AesEncryptor("1l23o0g9s5aesl11l1315");
        ss.setIvParameters("123");
        String sso = ss.encrypt("511702198209158764");
        System.out.println("AES=" + sso);
        String ssv = ss.decrypt(sso);
        System.out.println(ssv);
        System.out.println(ss.match("511702198209158764", sso, null));

        BlowfishEncryptor blowfishEncryptor = new BlowfishEncryptor("123");
        String bfEn = blowfishEncryptor.encrypt("123");
        System.out.println("Blowfish:" + bfEn);
        System.out.println("Blowfish:" + blowfishEncryptor.decrypt(bfEn));
        System.out.println(blowfishEncryptor.match("123", bfEn, null));

        String encrypt = bcryptEncrypt("test");
        System.out.println(encrypt);
        System.out.println(bcryptEncrypt("test"));
        System.out.println(bcryptEncrypt("test"));
        System.out.println(bcryptEncrypt(encrypt));
        System.out.println(bcryptMatch("test", encrypt));

    }
}
